import 'package:dio/dio.dart';
import 'package:get_storage/get_storage.dart';
import 'package:jss_flutter/http/global.dart';
import 'package:jss_flutter/utils/log_utils.dart';

import 'app_dio.dart';
import 'http_config.dart';
import 'http_parse.dart';
import 'http_response.dart';
import 'http_transformer.dart';

class HttpClient {
  late final AppDio _dio;

  HttpClient({BaseOptions? options, HttpConfig? dioConfig})
      : _dio = AppDio(options: options, dioConfig: dioConfig);

  /// 设置鉴权请求头
  Options _setAuthorizationHeader(Options requestOptions) {
    String token = Global.accessToken;
    if (token.isEmpty) {
      LogUtils.d("token is empty");
      var storageBox = GetStorage();
      token = storageBox.read("token");
      Global.accessToken = token;
      LogUtils.d("token=${Global.accessToken}");
    }
    if (token.isNotEmpty) {
      LogUtils.d("token1= $token");
      requestOptions.headers?['token'] = token;
    }
    return requestOptions;
  }

  /// 设置鉴权请求头
  Map<String, dynamic> _getAuthorizationHeader() {
    Map<String, dynamic> headers;
    String token = Global.accessToken;
    if (token.isEmpty) {
      LogUtils.d("token is empty");
      var storageBox = GetStorage();
      var saveToken = storageBox.read("token");
      if (saveToken != null) {
        token = storageBox.read("token");
        Global.accessToken = token;
        LogUtils.d("token=${Global.accessToken}");
      }
    }
    LogUtils.w("_token=$token");
    if (token.isNotEmpty) {
      headers = {
        'token': token,
      };
    } else {
      headers = {
        'token': "",
      };
    }
    return headers;
  }

  Future<HttpResponse> get(String uri,
      {Map<String, dynamic>? queryParameters,
      Options? options,
      CancelToken? cancelToken,
      ProgressCallback? onReceiveProgress,
      HttpTransformer? httpTransformer}) async {
    try {
      Options requestOptions = options ?? Options();
      Map<String, dynamic>? authorization = _getAuthorizationHeader();
      requestOptions = requestOptions.copyWith(headers: authorization);
      var response = await _dio.get(
        uri,
        queryParameters: queryParameters,
        options: requestOptions,
        cancelToken: cancelToken,
        onReceiveProgress: onReceiveProgress,
      );
      return handleResponse(response, httpTransformer: httpTransformer);
    } on Exception catch (e) {
      return handleException(e);
    }
  }

  Future<HttpResponse> post(String uri,
      {data,
      Map<String, dynamic>? queryParameters,
      Options? options,
      CancelToken? cancelToken,
      ProgressCallback? onSendProgress,
      ProgressCallback? onReceiveProgress,
      HttpTransformer? httpTransformer}) async {
    try {
      Options requestOptions = options ?? Options();
      Map<String, dynamic>? authorization = _getAuthorizationHeader();
      requestOptions = requestOptions.copyWith(headers: authorization);
      var response = await _dio.post(
        uri,
        data: data,
        queryParameters: queryParameters,
        options: requestOptions,
        cancelToken: cancelToken,
        onSendProgress: onSendProgress,
        onReceiveProgress: onReceiveProgress,
      );
      return handleResponse(response, httpTransformer: httpTransformer);
    } on Exception catch (e) {
      return handleException(e);
    }
  }

  Future<HttpResponse> patch(String uri,
      {data,
      Map<String, dynamic>? queryParameters,
      Options? options,
      CancelToken? cancelToken,
      ProgressCallback? onSendProgress,
      ProgressCallback? onReceiveProgress,
      HttpTransformer? httpTransformer}) async {
    try {
      Options requestOptions = options ?? Options();
      Map<String, dynamic>? authorization = _getAuthorizationHeader();
      requestOptions = requestOptions.copyWith(headers: authorization);
      var response = await _dio.patch(
        uri,
        data: data,
        queryParameters: queryParameters,
        options: requestOptions,
        cancelToken: cancelToken,
        onSendProgress: onSendProgress,
        onReceiveProgress: onReceiveProgress,
      );
      return handleResponse(response, httpTransformer: httpTransformer);
    } on Exception catch (e) {
      return handleException(e);
    }
  }

  Future<HttpResponse> delete(String uri,
      {data,
      Map<String, dynamic>? queryParameters,
      Options? options,
      CancelToken? cancelToken,
      HttpTransformer? httpTransformer}) async {
    try {
      Options requestOptions = options ?? Options();
      Map<String, dynamic>? authorization = _getAuthorizationHeader();
      requestOptions = requestOptions.copyWith(headers: authorization);
      var response = await _dio.delete(
        uri,
        data: data,
        queryParameters: queryParameters,
        options: requestOptions,
        cancelToken: cancelToken,
      );
      return handleResponse(response, httpTransformer: httpTransformer);
    } on Exception catch (e) {
      return handleException(e);
    }
  }

  Future<HttpResponse> put(String uri,
      {data,
      Map<String, dynamic>? queryParameters,
      Options? options,
      CancelToken? cancelToken,
      HttpTransformer? httpTransformer}) async {
    try {
      Options requestOptions = options ?? Options();
      Map<String, dynamic>? authorization = _getAuthorizationHeader();
      requestOptions = requestOptions.copyWith(headers: authorization);
      var response = await _dio.put(
        uri,
        data: data,
        queryParameters: queryParameters,
        options: requestOptions,
        cancelToken: cancelToken,
      );
      return handleResponse(response, httpTransformer: httpTransformer);
    } on Exception catch (e) {
      return handleException(e);
    }
  }

  Future<Response> download(String urlPath, savePath,
      {ProgressCallback? onReceiveProgress,
      Map<String, dynamic>? queryParameters,
      CancelToken? cancelToken,
      bool deleteOnError = true,
      String lengthHeader = Headers.contentLengthHeader,
      data,
      Options? options,
      HttpTransformer? httpTransformer}) async {
    try {
      var response = await _dio.download(
        urlPath,
        savePath,
        onReceiveProgress: onReceiveProgress,
        queryParameters: queryParameters,
        cancelToken: cancelToken,
        deleteOnError: deleteOnError,
        lengthHeader: lengthHeader,
        data: data,
        options: data,
      );
      return response;
    } catch (e) {
      rethrow;
    }
  }
}
